iT邦幫忙

2025 iThome 鐵人賽

DAY 7
0

匿名函式 (Anonymous function)

在 Elixir 中建立匿名函式
使用 fn 加上變數 接著用 ->end 寫函數內容,如下

fn(a, b) -> a + b end

# 通常忽略括號
fn a, b -> a + b end

我們發現這裡跟第一篇使用的 case 長的有點像 ->
這邊當然也是 pattern matching 因此多個條件會變成

fn
  _, 0 -> 0
  a, b -> div(a, b)
end

或是之前的例子

fn
  "Jack" -> "Welcome Admin Jack"
  "Sam" -> "VIP"
  name -> "Hi #{name}
end

把匿名函式傳入變數裡面當值

adder = fn a, b -> a + b end
greet = fn
  "Jack" -> "Welcome admin Jack"
  name -> "Hi #{name}"
end

匿名函數使用.() 來呼叫

adder = fn a, b -> a + b end

adder.(3, 4)
#=> 7
greet = fn
  "Jack" -> "Welcome admin Jack"
  name -> "Hi #{name}"
end

greet.("Jack") #=> "Welcome admin Jack"
greet.("Jimmy") #=> "Hi Jimmy"

高階函式

匿名函式可以做於高階函式的參數
我們這邊使用常用的 Enum.map/2 來示範

langs = ["elixir", "erlang", "ruby", "clojure", "elm"]

Enum.map(langs, fn lang -> String.upcase(lang) end)
#=> ["ELIXIR", "ERLANG", "RUBY", "CLOJURE", "ELM"]

在這邊我們在第二個變數帶入了 fn lang -> String.upcase(lang) end 這個匿名函數
想要的話也可以先放在變數,再帶入

langs = ["elixir", "erlang", "ruby", "clojure", "elm"]
upcase_fn = fn lang -> String.upcase(lang) end

Enum.map(langs, upcase_fn)
#=> ["ELIXIR", "ERLANG", "RUBY", "CLOJURE", "ELM"]

capture operator (&)

(無翻譯,我翻成"捕捉運算符")

如果匿名函式單純只有呼叫令一個函數,像剛剛的範例 fn lang -> String.upcase(lang) end
我們可以使用 & 直接把 String.upcase/1 抓住變成匿名函式

upcase_fn = &String.upcase/1

Enum.map(langs, upcase_fn)

更常見的是直接在參數上抓住

Enum.map(langs, &String.upcase/1)

變數不符合的時候

使用剛剛的語言列表
langs = ["elixir", "erlang", "ruby", "clojure", "elm"]
假如我們今天要將每個語言重複三次
使用匿名函式可以寫成

Enum.map(langs, fn lang -> String.duplicate(lang, 3) end)

#=> ["elixirelixirelixir", "erlangerlangerlang", "rubyrubyruby",
 "clojureclojureclojure", "elmelmelm"]

這邊因為 String.duplicate(lang, 3) 在呼叫時需要放入第二的參數
所以不能直接使用 & 抓取

不過這個時候可以使用 &1 來指定要帶入的位置,寫成

&Strig.duplicate(&1, 3)

使用起來會變成

Enum.map(langs, &String.duplicate(&1, 3))

& 也可以從頭開始定義匿名函式

搭配()&1, &2 可以讓它變得跟fn定義匿名函式一樣功能

adder = &(&1 + &2)

這個等同於

adder = fn x, y -> x + y end

不過這樣不能寫多行,也不能命名參數,但有的時候可以當作簡化寫法


上一篇
函式 2
下一篇
控制流程
系列文
通勤看手機就可讀懂的 Elixir 語言入門教學10
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言